//
//  NSArray+Safe.m
//  DebugDemo
//
//  Created by XFB on 2018/11/9.
//  Copyright © 2018年 ZhouCheng. All rights reserved.
//

#import "NSArray+Safe.h"
#import "NSObject+Swizzling.h"

//// 数组初始化类
//static NSString *KInitArrayClass  = @"__NSPlaceholderArray";
//// 多元素数组类，两个元素以上的数组
//static NSString *KMultiArrayClass  = @"__NSArrayI";
//// 空元素数组类，空数组
//static NSString *KEmptyArrayClass  = @"__NSArray0";
//// 单元素数组类，两个元素以上的数组
//static NSString *KSingleArrayClass = @"__NSSingleObjectArrayI";

@implementation NSArray (Safe)

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        /// 数组初始化
        [objc_getClass("__NSPlaceholderArray") swizzleSelector:@selector(initWithObjects:count:)
                                     withSwizzledSelector:@selector(zc_safeInitWithObjects:count:)];
        /// 多元素数组
        [objc_getClass("__NSArrayI") swizzleSelector:@selector(objectAtIndex:)
                                      withSwizzledSelector:@selector(zc_safeObjectAtIndex:)];
        /// 多元素数组
        [objc_getClass("__NSArrayI") swizzleSelector:@selector(objectAtIndexedSubscript:)
                                      withSwizzledSelector:@selector(zc_safeObjectAtIndexedSubscript:)];
        /// 空元素数组类
        [objc_getClass("__NSArray0") swizzleSelector:@selector(objectAtIndex:)
                                      withSwizzledSelector:@selector(zc_safeNullObjectAtIndex:)];
        /// 单元素数组类
        [objc_getClass("__NSSingleObjectArrayI") swizzleSelector:@selector(objectAtIndex:)
                                       withSwizzledSelector:@selector(zc_safeSingleObjectAtIndex:)];
    });
}

- (instancetype)zc_safeInitWithObjects:(const id _Nonnull __unsafe_unretained *)objects count:(NSUInteger)count
{
    BOOL hasNilObject = NO;
    for (NSUInteger i = 0; i < count; i ++) {
        if ([objects[i] isKindOfClass:[NSArray class]]) {
            NSLog(@"%@", objects[i]);
        }

        if (objects[i] == nil) {
            hasNilObject = YES;
            NSLog(@"%s object at index %lu is nil, it will be filtered", __FUNCTION__, i);
        }
    }
    
    /// 如果objec中有nil的元素，过滤掉为nil的元素
    if (hasNilObject) {
        id __unsafe_unretained newObjects[count];
        NSUInteger index = 0;
        for (NSUInteger i = 0; i < count; ++ i) {
            if (objects[i] != nil) {
                newObjects[index++] = objects[i];
            }
        }
        return [self zc_safeInitWithObjects:newObjects count:index];
    }
    
    return [self zc_safeInitWithObjects:objects count:count];
}


- (id)zc_safeObjectAtIndex:(NSUInteger)index
{
    if (self.count == 0 || index > self.count) {
        @try {
            return [self zc_safeObjectAtIndex:index];
        } @catch (NSException *exception) {
            /// 抛出异常
            NSLog(@"%@", [exception callStackSymbols]);
            return nil;
        } @finally {}
    } else {
        return [self zc_safeObjectAtIndex:index];
    }
}

- (id)zc_safeObjectAtIndexedSubscript:(NSUInteger)index
{
    if (self.count == 0 || index >= self.count) {
        @try {
            return [self zc_safeObjectAtIndexedSubscript:index];
        } @catch (NSException *exception) {
            /// 抛出异常
            NSLog(@"%@", [exception callStackSymbols]);
            return nil;
        } @finally {}
    } else {
        return [self zc_safeObjectAtIndexedSubscript:index];
    }
}

- (id)zc_safeNullObjectAtIndex:(NSUInteger)index
{
    if (self.count == 0) {
        @try {
            return [self zc_safeNullObjectAtIndex:index];
        } @catch (NSException *exception) {
            /// 抛出异常
            NSLog(@"%@", [exception callStackSymbols]);
        } @finally {}
    } else {
        return [self zc_safeNullObjectAtIndex:index];
    }
}


- (id)zc_safeSingleObjectAtIndex:(NSUInteger)index
{
    if (self.count == 0 || index >= self.count) {
        @try {
            return [self zc_safeSingleObjectAtIndex:index];
        } @catch (NSException *exception) {
            /// 抛出异常
            NSLog(@"%@", [exception callStackSymbols]);
            return nil;
        } @finally {}
    } else {
        return [self zc_safeSingleObjectAtIndex:index];
    }
}

@end
